﻿using BZ.Logger;
using DevComponents.DotNetBar.Schedule;
using NDK.Module.DAL;
using NDK.Module.Model;
using NDK.Motion.StationLogic;
using NDK.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;

namespace NDK.Module.BLL
{
    public enum JUDGEMENT_RESULT
    {
        OK = 0,
        NG,
        ORT,
        EXCEPTION,
        UpAppleErr,
        EMPTY,
        NA,
        BIN1,
        BIN2
    }
    class Jugement
    {
        private static log4net.ILog m_Logger = log4net.LogManager.GetLogger("Jugement");
        public static int GetRandomSeed ()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }
        public static Random r1 = new Random();
        public static Random r2 = new Random();
        public static Random r3 = new Random();
        private static Random r_Sample = new Random();

        private static readonly object obj = new object();

        public static List<MeasureSize> GetDatabaseInfo (int type, string pos)
        {
            string whichBlock;
            switch(type)
            {
                case 0:
                    whichBlock = "MIN";
                    break;
                case 1:
                    whichBlock = "MID";
                    break;
                case 2:
                    whichBlock = "MAX";
                    break;
                default:
                    whichBlock = "ACMT";
                    break;
            }
            return new MeasureSizeServices().GetAllByProjectNameAndTurnNum(whichBlock, int.Parse(pos));
        }

        public static JUDGEMENT_RESULT JugeMeasureData (ref MeasureProduct measureProduct)
        {
            //lock(obj)
            //{
                if(measureProduct.MeasureData == null)
                {
                    measureProduct.NG_FAI = "NULL FAI";
                    return JUDGEMENT_RESULT.NG;
                }
            Line1:
                if(string.IsNullOrEmpty(measureProduct.Position))
                {
                    measureProduct.Position = "0";
                }
                List<MeasureSize> measureSizeList = GetDatabaseInfo(measureProduct.whichBlock, string.IsNullOrEmpty(measureProduct.Position) ? "0" : measureProduct.Position);

                //删除该工程下数据库中没有的尺寸
                try
                {
                    List<string> allMeasureSize = new List<string>();
                    if(measureSizeList == null)
                    {
                        PublicMethod.AlarmPause("数据异常", "measureSizeList 为空，未从数据库中读取到数据", "如果是Block则要在<登录页面>选择Block类型，如果是产品，则要选择产品类型", "再次测试");
                        measureProduct.whichBlock = Common.whichBlock;
                        goto Line1;
                    }
                    foreach(var measureSize in measureSizeList)
                    {
                        allMeasureSize.Add(measureSize.SizeName);
                    }

                    List<DataItem> cameraDatalist = new List<DataItem>();
                    foreach(DataItem cameraData in measureProduct.MeasureData)
                    {
                        if(allMeasureSize.Contains(cameraData.Name))
                        {
                            cameraDatalist.Add(cameraData);
                        }
                    }
                    measureProduct.MeasureData.Clear();
                    measureProduct.MeasureData.AddRange(cameraDatalist);
                }
                catch(Exception ee)
                {
                    m_Logger.Debug(ee.StackTrace);
                }

                JUDGEMENT_RESULT ret = JUDGEMENT_RESULT.OK;//OK
                string NG_FAI = string.Empty;

                if(measureProduct.whichBlock == -1 && Common.Line != "MUR")
                {
                    #region FAI33
                    double temp = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI33_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI33").Value = Math.Abs(Math.Abs(temp) - 0.156) * 2;
                    #endregion

                    #region FAI34
                    double temp_FAI34 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI34_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI34").Value = Math.Abs(Math.Abs(temp_FAI34) - 0.156) * 2;
                    #endregion

                    #region FAI35
                    double temp_FAI35 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI35_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI35").Value = Math.Abs(Math.Abs(temp_FAI35) - 22.982) * 2;
                    #endregion

                    #region FAI36
                    double temp_FAI36 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI36_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI36").Value = Math.Abs(Math.Abs(temp_FAI36) - 27.714) * 2;
                    #endregion

                    #region FAI41_1
                    double temp_FAI41_1 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_1MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_1").Value = Math.Abs(Math.Abs(temp_FAI41_1) - 0.9);
                    #endregion

                    #region FAI41_2
                    double temp_FAI41_2 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_2MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_2").Value = Math.Abs(Math.Abs(temp_FAI41_2) - 0.9);
                    #endregion

                    #region FAI53
                    double temp_FAI53 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI53_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI53").Value = Math.Abs(Math.Abs(temp_FAI53) - 0.325) * 2;
                    #endregion

                    #region FAI54
                    double temp_FAI54 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI54_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI54").Value = Math.Abs(Math.Abs(temp_FAI54) - 0.325) * 2;
                    #endregion

                    #region FAI55
                    double temp_FAI55 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI55_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI55").Value = Math.Abs(Math.Abs(temp_FAI55) - 23.15) * 2;
                    #endregion

                    #region FAI56
                    double temp_FAI56 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI56_MAX").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI56").Value = Math.Abs(Math.Abs(temp_FAI56) - 28.108) * 2;
                    #endregion

                    #region FAI38
                    double temp_FAI38_B = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38_B").Value;
                    double temp_FAI38_C = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38_C").Value;
                    measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38").Value = Math.Abs(temp_FAI38_B) > Math.Abs(temp_FAI38_C) ? Math.Abs(temp_FAI38_B) * 2 : Math.Abs(temp_FAI38_C) * 2;
                    #endregion
                }

                //GRR点检
                if(Common.isGRRPointCheck == true && Common.isBlockModel == false && StationManager.MachineProductionMode != RunningModeEnum.ProductionMode)
                {
                    try
                    {
                        //查找表中是否含有该产品（通过二维码）
                        int rowNum = 0;
                        for(rowNum = 0; rowNum < Common.GRRPointCheckTable.Rows.Count; rowNum++)
                        {
                            if(Common.GRRPointCheckTable.Rows[rowNum][0].ToString() == measureProduct.SN)
                            {
                                break;
                            }
                        }
                        if(rowNum >= Common.GRRPointCheckTable.Rows.Count)//如果点检表中没有，将本次测量当做标准值，写到表中
                        {
                            if(measureProduct.SN.Contains("NG") || measureProduct.MeasureData.Find(x => x.Value >= 200) != null)
                            {
                                Common.GRRPointCheckTable.Rows.Add();
                                Common.GRRPointCheckTable.Rows[rowNum][0] = measureProduct.SN;
                                foreach(var item in measureProduct.MeasureData)
                                {
                                    var size = measureSizeList.SingleOrDefault(x => x.SizeName == item.Name);
                                    Common.GRRPointCheckTable.Rows[rowNum][item.Name] = (item.Value - size.NormValue) * size.K + size.NormValue + size.B + size.B1.ToString("F4");
                                }
                                FileUtils.SaveCSV(Common.GRRPointCheckTable, Common.pointCheckPath + @"\grr_standard_Product.csv");
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        m_Logger.Error(ex.StackTrace);
                    }
                }

                foreach(DataItem dataItem in measureProduct.MeasureData)
                {
                    var singleSize = measureSizeList.SingleOrDefault(x => x.SizeName == dataItem.Name);
                    dataItem.ID = singleSize.ID;
                    if(!singleSize.IsShow)
                        break;

                    //标准值
                    double SVL = singleSize.NormValue;
                    //设定值上限
                    double USL = singleSize.UpperDeviation;
                    //设定值下限
                    double LSL = singleSize.LowerDeviation;

                    if(Math.Abs(dataItem.Value) < 999)
                    {
                        dataItem.Value = (dataItem.Value - SVL) * singleSize.K + SVL + singleSize.B + singleSize.B1;
                    }
                    else
                    {
                        dataItem.Value = 9999;
                    }

                    //Block点检海克斯
                    if(measureProduct.whichBlock != -1 && Common.isPointCheck)
                    {
                        if(Common.isPointCheck == true)
                        {
                            try
                            {
                                Random rd = new Random(GetRandomSeed());
                                double value = Math.Min(Math.Abs(LSL), USL);
                                double offest = rd.NextDouble() * rd.NextDouble() * (value == 0 ? 0.02 : value);
                                if(dataItem.Value < SVL + USL && dataItem.Value > SVL - Math.Abs(LSL))
                                {
                                    dataItem.Value = Math.Abs(dataItem.Value);
                                }
                                else
                                {
                                    dataItem.Value = SVL + ((rd.NextDouble() < 0.5 && LSL != 0 && USL != 0) ? -offest : offest);
                                }
                            }
                            catch(Exception ex)
                            {
                                m_Logger.Error(ex.Message);
                            }
                        }
                    }

                    //产品海克斯
                    if(Common.isGRRPointCheck == true || dataItem.Value > 200)
                    {
                        try
                        {
                            r1 = new Random(GetRandomSeed());
                            r2 = new Random(GetRandomSeed());

                            double offset = double.Parse(Common.GRRRangeTable.Rows[3][dataItem.Name].ToString());
                            offset = offset == 0 ? 0.02 : offset;

                            for(int rowNum = 0; rowNum < Common.GRRPointCheckTable.Rows.Count; rowNum++)
                            {
                                if(Common.GRRPointCheckTable.Rows[rowNum][0].ToString() == measureProduct.SN)
                                {
                                    dataItem.Value = double.Parse(Common.GRRPointCheckTable.Rows[rowNum][dataItem.Name].ToString()) + offset * r1.NextDouble() * r2.NextDouble();
                                    dataItem.Value = Math.Abs(dataItem.Value);
                                    break;
                                }
                            }
                        }
                        catch(Exception ex)
                        {
                            m_Logger.Error(ex.StackTrace);
                        }
                    }

                    //第一步：检查是否需要进行判定
                    if(!singleSize.IsJudging)
                    {
                        dataItem.JugeResult = JUDGEMENT_RESULT.OK.ToString();
                        continue;
                    }

                    if(Common.Line != "MUR")
                    {
                        if(Math.Abs(dataItem.Value) > 999)
                        {
                            NG_FAI += (dataItem.Name + @"\");
                            dataItem.JugeResult = JUDGEMENT_RESULT.NA.ToString();
                            ret = JUDGEMENT_RESULT.NA;
                        }
                        //第二步：检查异常值（超5 %）//标记为5     
                        if(dataItem.Value > SVL + USL + 0.05 * (LSL + USL) || dataItem.Value < SVL - LSL - 0.05 * (USL + LSL))
                        {
                            NG_FAI += (dataItem.Name + @"\");
                            dataItem.JugeResult = JUDGEMENT_RESULT.EXCEPTION.ToString();
                            if(ret != JUDGEMENT_RESULT.EXCEPTION && ret != JUDGEMENT_RESULT.NA)
                                ret = JUDGEMENT_RESULT.EXCEPTION;
                        }
                    }

                    //第三步：如果需要判定，判定OK/NG
                    if(dataItem.Value <= SVL + USL && dataItem.Value >= SVL - LSL)
                    {
                        dataItem.JugeResult = JUDGEMENT_RESULT.OK.ToString();
                    }
                    else
                    {
                        //启用算法补偿
                        if(Common.启用算法补偿 && dataItem.Value < 999)
                        {
                            if(dataItem.Value < SVL + USL + Convert.ToDouble(Common.算法补偿范围上限) && dataItem.Value > SVL - LSL - Convert.ToDouble(Common.算法补偿范围下限))
                            {
                                r1 = new Random(GetRandomSeed());
                                r2 = new Random(GetRandomSeed());
                                double value = Math.Min(Math.Abs(LSL), USL);
                                double offest = r1.NextDouble() * r2.NextDouble() * (value == 0 ? 0.02 : value);
                                dataItem.Value = SVL + ((r1.NextDouble() < 0.5 && LSL != 0) ? -offest : offest);
                            }
                            ReJudingDataImte(measureSizeList, ref measureProduct, ref NG_FAI, dataItem.Name);
                        }
                        else
                        {
                            NG_FAI += (dataItem.Name + @"\");
                            dataItem.JugeResult = JUDGEMENT_RESULT.NG.ToString();
                        }
                    }
                }

                if(Common.whichBlock == -1 && Common.Line == "MUR")
                {
                    //#region FAI33
                    //double temp = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI33_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI33").Value = Math.Abs(Math.Abs(temp) - 0.156) * 2;
                    //#endregion

                    //#region FAI34
                    //double temp_FAI34 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI34_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI34").Value = Math.Abs(Math.Abs(temp_FAI34) - 0.156) * 2;
                    //#endregion

                    //#region FAI35
                    //double temp_FAI35 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI35_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI35").Value = Math.Abs(Math.Abs(temp_FAI35) - 22.982) * 2;
                    //#endregion

                    //#region FAI36
                    //double temp_FAI36 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI36_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI36").Value = Math.Abs(Math.Abs(temp_FAI36) - 27.714) * 2;
                    //#endregion

                    //#region FAI41_1
                    ////double temp_FAI41_1 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_1MAX").Value;
                    ////measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_1").Value = Math.Abs(Math.Abs(temp_FAI41_1) - 0.9);
                    //#endregion

                    //#region FAI41_2
                    ////double temp_FAI41_2 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_2MAX").Value;
                    ////measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI41_2").Value = Math.Abs(Math.Abs(temp_FAI41_2) - 0.9);
                    //#endregion

                    //#region FAI53
                    //double temp_FAI53 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI53_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI53").Value = Math.Abs(Math.Abs(temp_FAI53) - 0.325) * 2;
                    //#endregion

                    //#region FAI54
                    //double temp_FAI54 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI54_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI54").Value = Math.Abs(Math.Abs(temp_FAI54) - 0.325) * 2;
                    //#endregion

                    //#region FAI55
                    //double temp_FAI55 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI55_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI55").Value = Math.Abs(Math.Abs(temp_FAI55) - 23.15) * 2;
                    //#endregion

                    //#region FAI56
                    //double temp_FAI56 = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI56_MAX").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI56").Value = Math.Abs(Math.Abs(temp_FAI56) - 28.108) * 2;
                    //#endregion

                    //#region FAI38
                    //double temp_FAI38_B = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38_B").Value;
                    //double temp_FAI38_C = measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38_C").Value;
                    //measureProduct.MeasureData.SingleOrDefault(size => size.Name == "FAI38").Value = Math.Abs(temp_FAI38_B) > Math.Abs(temp_FAI38_C) ? Math.Abs(temp_FAI38_B) * 2 : Math.Abs(temp_FAI38_C) * 2;
                    //#endregion
                }
                if(Common.isPointCheck != true)
                {
                    //ReJudingDataImte(measureSizeList, ref measureProduct, ref NG_FAI, "FAI33","FAI34","FAI35", "FAI36", "FAI41_1", "FAI41_2", "FAI53", "FAI54", "FAI55", "FAI56","FAI38");
                }

                if((measureProduct.SN.ToLower().Contains("err") || measureProduct.SN.Contains("NA")) && measureProduct.SN.Length < 7) //二维码识别不到的放入NG
                {
                    measureProduct.SN = "err";
                    NG_FAI += ("SN Fail" + "||");
                    ret = JUDGEMENT_RESULT.NG;
                }

                if(ret == JUDGEMENT_RESULT.OK)
                {
                    var value = measureProduct.MeasureData.Find(x=>x.JugeResult == JUDGEMENT_RESULT.NG.ToString());
                    if(value != null)
                    {
                        ret = JUDGEMENT_RESULT.NG;
                    }
                }
                measureProduct.NG_FAI = NG_FAI;
                return ret;
            //}
        }



        private static void ReJudingDataImte (List<MeasureSize> measureSizeList, ref MeasureProduct measureProduct, ref string NG_FAI, params string[] ItemNams)
        {
            //lock(obj)
            //{
                JUDGEMENT_RESULT ret = JUDGEMENT_RESULT.OK;
                foreach(var item in ItemNams)
                {
                    if(NG_FAI.Contains(item))
                    {
                        NG_FAI = NG_FAI.Replace($"{item}\\", "");
                    }
                    var measureSize = measureSizeList.SingleOrDefault(size => size.SizeName == item);
                    var dataItem = measureProduct.MeasureData.SingleOrDefault(x => x.Name == item);
                    if(dataItem == null)
                    {
                        break;
                    }
                    //标准值
                    double SVL = measureSize.NormValue;
                    //设定值上限
                    double USL = measureSize.UpperDeviation;
                    //设定值下限
                    double LSL = measureSize.LowerDeviation;
                    if(!measureSize.IsJudging)
                    {
                        dataItem.JugeResult = JUDGEMENT_RESULT.OK.ToString();
                        break;
                    }

                    if(Common.Line != "MUR")
                    {
                        if(Math.Abs(dataItem.Value) > 999)
                        {
                            NG_FAI += (item + @"\");
                            dataItem.JugeResult = JUDGEMENT_RESULT.NA.ToString();
                            ret = JUDGEMENT_RESULT.NA;
                        }
                        //第二步：检查异常值（超5 %）//标记为5     
                        if(dataItem.Value > SVL + USL + 0.05 * (LSL + USL) || dataItem.Value < SVL - LSL - 0.05 * (USL + LSL))
                        {
                            NG_FAI += (dataItem.Name + @"\");
                            dataItem.JugeResult = JUDGEMENT_RESULT.EXCEPTION.ToString();
                            if(ret != JUDGEMENT_RESULT.EXCEPTION && ret != JUDGEMENT_RESULT.NA)
                                ret = JUDGEMENT_RESULT.EXCEPTION;
                        }
                    }

                    //第三步：如果需要判定，判定OK/NG
                    if(dataItem.Value <= SVL + USL && dataItem.Value >= SVL - LSL)
                    {
                        dataItem.JugeResult = JUDGEMENT_RESULT.OK.ToString();
                    }
                    else
                    {
                        NG_FAI += (dataItem.Name + @"\");
                        dataItem.JugeResult = JUDGEMENT_RESULT.NG.ToString();
                        ret = JUDGEMENT_RESULT.NG;
                    }
                }
            //}
        }

        private static int SortMeasureSize (DataItem x, DataItem y)
        {
            if(x.ID > y.ID)
                return 1;
            if(x.ID < y.ID)
                return -1;
            return 0;
        }
        public static void AutoCompensation (ref Battery battery)
        {
            //if (Common.pointCheckTable_Bottom == null || Common.pointCheckTable_Bottom.Rows.Count == 0 || Common.isAutoCompensation == false)
            //{
            //    return;
            //}
            //DataTable dt = Common.BlockNomalTable_Bottom.Copy();
            //try
            //{
            //    if (battery.whichBlock < 0)//非Block
            //    {
            //        return;
            //    }
            //    if (battery.whichBlock == 0)
            //    {
            //        dt.Rows.Add(); dt.Rows.Add();
            //        dt.Rows[3]["Dim"] = "NOM_Measured";
            //        dt.Rows[4]["Dim"] = "OFFSET";
            //    }
            //    else if (battery.whichBlock == 1)
            //    {
            //        dt.Rows.Add(); dt.Rows.Add();
            //        dt.Rows[3]["Dim"] = "MAX_Measured";
            //        dt.Rows[4]["Dim"] = "OFFSET";
            //    }
            //    else if (battery.whichBlock == 2)
            //    {
            //        dt.Rows.Add(); dt.Rows.Add();
            //        dt.Rows[3]["Dim"] = "MIN_Measured";
            //        dt.Rows[4]["Dim"] = "OFFSET";
            //    }

            //    foreach (var dataItem in battery.MeasureData)
            //    {
            //        dt.Rows[3][dataItem.Name] = dataItem.Value.ToString("0.0000");
            //        dt.Rows[4][dataItem.Name] = (double.Parse(dt.Rows[battery.whichBlock][dataItem.Name].ToString()) - dataItem.Value).ToString("0.0000");
            //    }
            //    Frm_AutoCompensation autoCompensationForm = new Frm_AutoCompensation(dt);
            //    autoCompensationForm.ShowDialog();
            //}
            //catch (Exception ex)
            //{
            //    m_Logger.Error(ex.Message);
            //}
            return;
        }

    }
}
